[comment encoding = UTF-8 /] [** * The documentation of the module generate. * * EROR FOUND IN THE ABSTRACT SYNTAX FROM FUML * TypedElement is an abstract metaclass - according to UML 2.4.1, Typed element is an abstract metaclass. * Class does not have the attribute isID - according UML 2.4.1 and fUML document * * Tree options to represent hierarchy in sets * one set discriminator * set for each class * set for each concrete class * * * * http://www.haskell.org/haskellwiki/Polymorphism * There are some kinds of polymorphism that Haskell doesn't support, or at least not natively, e.g. inclusion polymorphism and subtyping, common in OO languages, where values of one type can act as values of another type. * * * * 1. SELECTION: ONLY LEAF NODES - set for each concrete class, with closure of features (for classes abstract) - Class, e.g. was not generated because BehavioredClassifier extends Class * 2. SELECTION: ENCODE ALL HIERARCHY - Techniche to encode hierarchy is from http://research.microsoft.com/en-us/um/people/simonpj/Papers/oo-haskell/overloading.pdf - It generates a ruge problem with references * 3. SELECTION: SELECT MANUALLY SPECIAL CLASSES IN THE MIDDLE OF HIERARCHY AND GENERATE ALL AS A ONE TYPE USING UNION TYPE FOR CONCRETE SUBCLASS - It does not allow to see attribute, there is a hudge ammount of code for each data constructor * 4. SELECTION: SELECT MANUALLY SPECIAL CLASSES IN THE MIDDLE OF HIERARCHY AND GENERATE ALL AS A ONE TYPE WHOLE SUBSET WITH ENUMERATION TO CHECK TYPE DOW - It worked, we could use a typeclass for abstract elements, but it is not so usefull now. * * * SPECIAL treatment: * PrimitiveTypes - translation for haskell/gofer datatype - 'PrimitiveTypes','Boolean','String','Integer','UnlimitedNatural','Real' * Activity.ownedNode - workaround from eclipse for this (should include elements in the structuredActivityNodes or not) * NamedElement - for comparison * context - reserved work in acceleo, and implemented as _context in Eclipse * NameSpace * RedefinableElement * NamedElement - cannot be generated in the transformation, it has no representation in the embedde model * body - reserved work in acceleo, and implemented as _body in Eclipse * Activity * .ownedAttribute - ERROR in Eclipse (bug) returns elements that are not a property * TypedElement - defined cross cutting elements, but IT DOES NOT WORK because AsmGofer does not treat well circular references(easily created using types) DO NOT TRY to add this cross cutting class. * - Therefore, it is still creating new functions for types * Semantics - no parameters in the data constructors, everything is a dynamic function * - However, it should be manually implemented an EQ operation, e.g. instants and value * Semantics - removed evaluation because it is impossible to embed it * Syntax - created filter for generation of functions for stereotype * - loaded elements from other model (if selected, it is effective in the generated transformation) * */] [module embeddingM2_ASM('http://www.eclipse.org/uml2/4.0.0/UML')] [** query public getTargetElements(o:OclAny) : Set (String) = Set{'Executor','ExecutionFactory','Locus','ObjectToken','ControlToken','Offer','ActivityExecution','BooleanValue','IntegerValue','Object','DataValue','SignalInstance','Reference','FeatureValue','Signal','Class','Activity','Parameter','SystemOfEquations','RealValue','UnlimitedNaturalValue','StringValue', 'DiscreteTimeBase', 'MultipleTimeBase', 'JunctionInstant','LogicalClock','PhysicalClock','RealNegExecution','RealMultExecution','RealMinusExecution','RealAddExecution','RealLessThanOrEqualExecution','BooleanAndExecution','BooleanNotExecution','ParameterValue'}/ query public getKeyElements(o:OclAny) : Set (String) = Set{'Executor','ExecutionFactory','Locus','Token','Offer','Value', 'FeatureValue', 'ParameterValue','SystemOfEquations', 'Classifier','ValueSpecification','Parameter','Feature','Constraint','TimeBase', 'MultipleTimeBase', 'Instant','Clock','Event'}/ query public getKeyElementsInOtherModule(o:OclAny) : Set (String) = Set{'Classifier','ValueSpecification','Parameter','Feature','Constraint','VisibilityKind','ParameterDirectionKind','Constraint','Event'}/ query public generateSemantics(o:OclAny) : Boolean = true / query public getAllowedStereotypes(o:OclAny) : Set (String) = Set{} / query public getCrossCuttingElements(o:OclAny) : Set (String) = Set{}/ query public getNotGenerateEQ(o:OclAny) : Set (String) = Set{} / query public getElementsWithStereotype(o:OclAny) : Set (String) = Set{} / query public getElementsFromOtherModel(o:OclAny) : Set (String) = Set{} / query public getElementsToBeGeneratedStereotype(o:OclAny) : Set (String) = Set{} / query public getElementsToBeGeneratedStereotypeAttribute(o:OclAny) : Set (String) = Set{}/ */] [query public getTargetElements(o:OclAny) : Set (String) = Set{ 'DataType' ,'LiteralReal' ,'Constraint' ,'ControlFlow' ,'SendSignalAction' ,'FlowFinalNode' ,'Property' ,'ReadStructuralFeatureAction' ,'ObjectFlow' ,'MergeNode' ,'PrimitiveType' ,'ReadSelfAction' ,'CreateObjectAction', 'EncapsulatedClassifier' ,'CallBehaviorAction' ,'InputPin' ,'LiteralBoolean' ,'Parameter' ,'StructuredClassifier' ,'StartObjectBehaviorAction' ,'LiteralUnlimitedNatural' ,'InitialNode' ,'LiteralInteger' ,'Signal' ,'OutputPin' ,'Connector' ,'ConnectorEnd' ,'Port' ,'Activity' ,'Reception' ,'RemoveStructuralFeatureValueAction' ,'Class' ,'DecisionNode' ,'AcceptEventAction' ,'LiteralString' ,'AddStructuralFeatureValueAction' ,'ForkNode' ,'ValueSpecificationAction' ,'FunctionBehavior', 'LiteralNull', 'SignalEvent', 'Trigger', 'ClearStructuralFeatureAction', 'InstanceValue','InstanceSpecification','Slot'}/] [query public getKeyElements(o:OclAny) : Set (String) = Set{'ConnectorEnd','ActivityNode','Classifier','Constraint','ValueSpecification','Parameter','ActivityEdge','Feature', 'Event', 'Trigger','InstanceSpecification','Slot'} /] [query public getKeyElementsInOtherModule(o:OclAny) : Set (String) = Set{} /] [query public generateSemantics(o:OclAny) : Boolean = false /] [query public getAllowedStereotypes(o:OclAny) : Set (String) = Set{ 'ContinuousDomain' ,'ModelicaConnection' ,'NonBlockable' ,'StereotypeUndef' ,'ModelicaConnector' ,'DiscreteDomain' ,'Pausable' ,'ModelicaPort' ,'ModelicaValueProperty' ,'ModelicaEquation', 'Clock', 'ClockConstraint', 'Previous', 'Edge','PrecededBy'} /] [query public getCrossCuttingElements(o:OclAny) : Set (String) = Set{'MultiplicityElement'} /] [query public getNotGenerateEQ(o:OclAny) : Set (String) = Set{} /] [query public getElementsWithStereotype(o:OclAny) : Set (String) = Set{'Classifier','ActivityNode','Event','Constraint','Feature'} /] [query public getElementsFromOtherModel(o:OclAny) : Set (String) = Set{} /] [query public getElementsToBeGeneratedStereotype(o:OclAny) : Set (String) = Set{'ValueSpecification'} /] [query public getElementsToBeGeneratedStereotypeAttribute(o:OclAny) : Set (String) = Set{'initialValue'} /] [** * The documentation of the template generateElement. * @param anElement */] [template public generateModel(aModel : Model)] [comment @main/] [file ('embeddedM2.gs', false, 'UTF-8')] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- Generated for METAMODEL: [aModel.name/] [if (not generateSemantics() )] -- SYNTAX [else] -- SEMANTICS [/if] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- EVALUATING MODEL, TARGET ELEMENTS AND KEY ELEMENTS -- TARGET ELEMENTS: [for (aClass:String | getTargetElements())] [aClass/][/for] -- KEY ELEMENTS: [for (aClass:String | getKeyElements())] [aClass/][/for] -- TARGET CLASSIFIERS: [for (aClass:Classifier | getTargetClassifiers()->asSequence()->sortedBy(name))] -- [aClass.name/] [/for] -- KEY CLASSIFIERS: [for (aClass:Classifier | getKeyClassifiers()->asSequence()->sortedBy(name))] -- [aClass.name/] [/for] -- CROSS CUTTING CLASSIFIERS: [for (aClass:Classifier | getCrossCuttingClassifiers()->asSequence()->sortedBy(name))] -- [aClass.name/] [/for] -- will some target elements be lost? [if (getTargetClassifiers() ->size() <> getTargetElements()->size())]YES. -- ERROR: target elements are lost [else] no [/if] -- checking closure -- evaluating closure for [getTargetElements()/] -- using this key elements [getKeyElements()/] -- closed? [ isTargetClassifiersClosedUnderKeyClassifiers()/] -- outside elements [ getClassifiersOutside().name/] -- removing those elements -- will some key elements be lost? [if (getKeyClassifiers() ->intersection(getClassifiersOutside())->size()>0)]YES. -- ERROR: key elements are lost [else] no [/if] -- closed? true -- are they elements to be processed? [if (getElementsToBeProcessed()->size()=0)] no -- ERROR: nothing to process [else] yes [/if] -- checking elements -- evaluating class hierarchy for [getKeyElements()/] -- entire class hierarchy is pair wise disjoint for elements... [for (aClass:Classifier | getKeyClassifiers())] [for (aClass2:Classifier | getKeyClassifiers())] [if aClass <> aClass2 and (getAllSuperClasses(aClass.oclAsType(Class))->union(getAllSubClasses(aClass2.oclAsType(Class))))->includes(aClass2)] -- ERROR: class hierarchy conflict [aClass.name/] [aClass2.name/] [/if][/for][/for] -- checking attributes from elements -- looking for inconsistencies: multiple types for a given atttribute, attribute uses a Bag or an OrdererSet, attribute without type [for (aClass:Class | getKeyClassifiers()->filter(Class))] [for (p:Property | getAllAttributesToBeGenerated(aClass))] [if (getTypeToBeConsidered(p.type)->size()<>1 and not isAPrimitiveType(p.type))] -- WARNING: multiply types for the attribute [p.name/] [getTypeToBeConsidered(p.type).name/] - different functions will be available [/if] [if (not p.isUnique and not p.isOrdered)] -- ERROR: attribute uses a Bag [p.name/] [getTypeToBeConsidered(p.type).name/] [/if] [if (p.isUnique and p.isOrdered)] -- WARNING: attribute uses an OrderedSet [p.name/] [getTypeToBeConsidered(p.type).name/] but it is mapped to a Set [/if] [/for] [for (p:Property | getAllAttributes(aClass))] [if (p.type = null or p.type.oclIsInvalid() or p.type.namespace.oclIsInvalid())] -- ERROR: attribute without type - Class: [aClass.name/] Attribute: [p.name/] [/if] [/for] [/for] -- checking associations owning more than one ends, associations owning one end is covered by data types -- embedding generates properties owned by a classifier using two strategies: not navigable are defined in the data type constructor, navigable are generated in the generated transformation (criteria used: opposite is empty, i.e. other end is not navigable) [for (a:Association | Association.allInstances())] [if (a.ownedEnd->size() >1 )] -- ERROR: Association is not generated: [a.name/] [for (p:Element | a.ownedEnd)] -- ERROR: Attribute: [p.oclAsType(NamedElement).name/] [/for] [/if] [/for] -- generating these elements: [for (aClass:Classifier | getElementsToBeProcessed())] -- [aClass.name/][if (aClass.oclIsKindOf(Class) and aClass.oclAsType(Class).getAllSuperClassesWithoutMe()->size()>0)] -- superclasses: [for (aClass2:Classifier | aClass.oclAsType(Class).getAllSuperClassesWithoutMe())] [aClass2.name/] [/for][/if][if (aClass.oclIsKindOf(Class) and aClass.oclAsType(Class).getAllSubClasses()->select(not isAbstract)->size()>0)] -- subclasses: [for (aClass2:Classifier | aClass.oclAsType(Class).getAllSubClasses()->select(not isAbstract))] [aClass2.name/] [/for][/if][if (aClass.oclIsKindOf(Class))] -- attributes(data constructors): [for (namedE:NamedElement | aClass.oclAsType(Class).getAllAttributesToBeGeneratedForConstructor())] [namedE.name/] [/for][/if] [/for] [getElementsToBeProcessed().generateElement()/] -- EVALUATED these elements - closed set: [for (aClass:Classifier | getTargetClassifiersClosure())] -- [aClass.name/][if (aClass.oclIsKindOf(Class) and aClass.oclAsType(Class).getAllSuperClassesWithoutMe()->size()>0)] -- superclasses: [for (aClass2:Classifier | aClass.oclAsType(Class).getAllSuperClassesWithoutMe())] [aClass2.name/] [/for][/if][if (aClass.oclIsKindOf(Class) and aClass.oclAsType(Class).getAllSubClasses()->select(not isAbstract)->size()>0)] -- subclasses: [for (aClass2:Classifier | aClass.oclAsType(Class).getAllSubClasses()->select(not isAbstract))] [aClass2.name/] [/for][/if] [/for] [/file] [if (not generateSemantics() )] [file ('embeddingM1_ASM.genmtl', false, 'UTF-8')] ['['/]** * * Generated for METAMODEL: [aModel.name/] * */[']'/] ['['/]module embeddingM1_ASM('http://www.eclipse.org/uml2/4.0.0/UML')[']'/] ['['/]template public generateModel(aModel : Model)[']'/] ['['/]comment @main/[']'/] ['['/]file ('3syntax_userModel_embedded.gs', false, 'UTF-8')[']'/] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- Generated for MODEL: ['['/]aModel.name/[']'/] [generateClosureEvaluation()/] [getElementsToBeProcessed().generateTransformationDataConstructors()/] [getElementsToBeProcessed()->select(getElementsWithStereotype()->includes(name)).generateTransformationStereotypeFunctions()/] [getKeyClassifiers().generateTransformationProperties()/] ['['/]/file[']'/] ['['/]/template[']'/] [generateHelpQueries()/] [/file] [/if] [/template] [template public generateElement(aElement : Classifier)] [let aClass : Class = aElement] [generateDataType(aClass)/] [/let] [let aEnum : Enumeration = aElement] [generateEnumeration(aEnum)/] [/let] [/template] [template public generateDataType(aClass : Class)] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- CLASS [generateName(aClass)/] [if (getAllSubClassesForType(aClass) -> size() > 0)] -- sub classes TYPES data [generateName(aClass)/]Type = [for (aClass2:Class | getAllSubClassesForType(aClass))][if (i>1 )] | [/if][generateName(aClass2)/][/for] instance AsmTerm [generateName(aClass)/]Type where asmDefault = [generateName(getAllSubClassesForType(aClass)->any(true))/] instance Ord [generateName(aClass)/]Type where [generateOrdEnumeration(aClass)/] instance Eq [generateName(aClass)/]Type where (==) = genericEq [/if] -- ([for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))] [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateName(p)/][elseif (p.isUnique)]{[generateName(p)/]}[elseif (p.isOrdered)] [ '[' /][generateName(p)/][ ']' /][/if][/for]) data [generateName(aClass)/] = [generateDataConstructor(aClass)/] instance AsmTerm [generateName(aClass)/] where asmDefault = [generateName(aClass)/]Empty instance Ord [generateName(aClass)/] where [if (getAllAttributesToBeGeneratedForConstructor(aClass) -> size() > 0 )] [generateOrd(aClass)/] [else] (<=) a b = genericLt a b || genericEq a b [/if] [if (getAllAttributesToBeGeneratedForConstructor(aClass) -> size() > 0 )]instance Eq [generateName(aClass)/] where [generateEq(aClass)/] [elseif (getNotGenerateEQ()->excludes(aClass.name))]instance Eq [generateName(aClass)/] where (==) = genericEq [/if] [if (getAllAttributesToBeGeneratedForConstructor(aClass) -> size() > 0 and getAllSuperClasses(aClass).name->includes('NamedElement'))] instance Text [generateName(aClass)/] where [generateText(aClass)/] [/if] [if (generateSemantics())] [if (getAllAttributesToBeGeneratedForConstructor(aClass) -> size() = 0 and getAllSubClassesForType(aClass) -> size() = 0)] instance Create [generateName(aClass)/] where createElem i = [generateName(aClass)/] i [else] [generateCreate(aClass)/] [/if] [/if] -------------------------------------- ATTRIBUTES -------------------------------------- --type [if (getAllSubClassesForType(aClass) -> size() > 0 )] [generateNameFunction(aClass,'type')/] :: [generateName(aClass)/] -> [generateName(aClass)/]Type [generateNameFunction(aClass,'type')/] ([generateDataConstructorParameter(aClass,'')/]) = [generateName(aClass).toLowerFirst()/]Type [/if] --class FUNCTIONS [generateName(aClass)/] [generateProperty(aClass, aClass)/] [for (aClass2:Class | getAllSuperClassesWithoutMe(aClass))] --super class FUNCTIONS [generateName(aClass2)/] [generateProperty(aClass, aClass2)/] [/for] [for (aClass2:Class | getAllSubClassesPlusCrossCutting(aClass))] --sub class FUNCTIONS [generateName(aClass2)/] [generateProperty(aClass, aClass2)/] [/for] -------------------------------------- OPERATIONS -------------------------------------- --class FUNCTIONS [generateName(aClass)/] [generateOperation(aClass, aClass)/] [for (aClass2:Class | getAllSuperClassesWithoutMe(aClass))] --super class FUNCTIONS [generateName(aClass2)/] [generateOperation(aClass, aClass2)/] [/for] [for (aClass2:Class | getAllSubClasses(aClass))] --sub class FUNCTIONS [generateName(aClass2)/] [generateOperation(aClass, aClass2)/] [/for] [/template] [template public generateEnumeration(aEnum : Enumeration)] ------------------------------------------------------------------------------------------------------------------------------------------------------------ data [generateName(aEnum)/] = [for (p:EnumerationLiteral | aEnum.ownedLiteral)] [if (i >1)]|[/if] [generateName(p)/] [/for] instance AsmTerm [generateName(aEnum)/] where asmDefault = [generateName(aEnum.ownedLiteral->any(true))/] instance Ord [generateName(aEnum)/] where [generateOrdEnumeration(aEnum)/] [/template] [** * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * SUPPORT */] [template public generateProperty(aClass:Class, aClass2:Class) ] [for (p:Property | aClass2.ownedAttribute)] [if (p.type.oclIsUndefined())] -- property not generated (TYPE UNDEFINED) [p.name/] [elseif (p.isDerived)] -- property not generated (DERIVED PROPERTY) [p.name/] [p.type.name/] [elseif (p.type.isAPrimitiveType() or getTypeToBeConsidered(p.type)->size() = 1)] [if (p.opposite ->isEmpty() )] -- property generated [p.name/] [p.type.name/] [if (shouldBeConsideredInConstructor(p))] [generateNameFunction(aClass,p)/] :: Dynamic ( [generateName(aClass)/] -> [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] ) [generateNameFunction(aClass,p)/] = [if (p.isUnique)]initAssocs' "[generateNameFunction(aClass,p)/]" [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][if (p.type.isAPrimitiveType())][generateDefaultValueForType(p)/][else]asmDefault[/if][else]{}[/if] asmLt (==) [ '[' /][ ']' /][elseif (p.isOrdered)]initAssocs' "[generateNameFunction(aClass,p)/]" [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][if (p.type.isAPrimitiveType())][generateDefaultValueForType(p)/][else]asmDefault[/if][else][ '[' /][ ']' /][/if] asmLt (==) [ '[' /][ ']' /][/if] [else] [generateNameFunction(aClass,p)/] :: [generateName(aClass)/] -> [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] [generateNameFunction(aClass,p)/] ([generateDataConstructorParameter(aClass,'')/]) = [for (p1:Property | getAllAttributesToBeGeneratedForConstructor(aClass))][if(p=p1)][p1.name/][i/][/if][/for] [/if] [else] [if (p.lower>0)] -- property - association with opposite side navigable ([p.opposite.name/]) mandatory lower([p.lower/]) - User must define a BODY [else] -- property - association with opposite side navigable ([p.opposite.name/]) - User can define a BODY [/if] [if (generateSemantics())] [generateNameFunction(aClass,p)/] :: Dynamic ( [generateName(aClass)/] -> [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] ) [generateNameFunction(aClass,p)/] = [if (p.isUnique)]initAssocs' "[generateNameFunction(aClass,p)/]" [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][if (p.type.isAPrimitiveType())][generateDefaultValueForType(p)/][else]asmDefault[/if][else]{}[/if] asmLt (==) [ '[' /][ ']' /][elseif (p.isOrdered)]initAssocs' "[generateNameFunction(aClass,p)/]" [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][if (p.type.isAPrimitiveType())][generateDefaultValueForType(p)/][else]asmDefault[/if][else][ '[' /][ ']' /][/if] asmLt (==) [ '[' /][ ']' /][/if] [else] -- [generateNameFunction(aClass,p)/] :: [generateName(aClass)/] -> [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] [/if] [/if] [else] -- property not generated (TYPE IS NOT IN THE CLOSED SET) [p.name/] [p.type.name/] [/if] [/for] [/template] [template public generateOperation(aClass:Class, aClass2:Class) ] [for (o:Operation | aClass2.ownedOperation)] [if (not o.hasReturn())] -- operation could be generated (THERE IS NO RETURN) -- [generateNameOperation(aClass,o)/] :: [generateName(aClass)/] -> [generateParameters(o)/] [if (generateSemantics())] Rule() [/if] -- [elseif (o.canBeGenerated())] -- operation could be generated [o.name/] [for (p:Parameter | o.getAllParameters())][p.name/]::[p.type.name/] [/for] -- [generateNameOperation(aClass,o)/] :: [generateName(aClass)/] -> [generateParameters(o)/] [if (generateSemantics())] Rule [/if][generateReturn(o)/] -- [else] -- operation could not be generated (SOME TYPE IS NOT IN THE CLOSED SET) [o.name/] [for (p:Parameter | o.getAllParameters())][p.name/]::[p.type.name/] [/for] [/if] [/for] [/template] [template public generateDataConstructor(aClass:Class) ] [generateName(aClass)/] [if (not generateSemantics() )]String[else]Int[/if][for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))] [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] [/for] [if (getAllSubClassesForType(aClass) -> size() > 0 )][generateName(aClass)/]Type[/if] | [generateName(aClass)/]Empty [/template] [template public generateDataConstructorParameter(aClass:Class, prefix:String) ] [generateName(aClass)/] [if (not generateSemantics() )][prefix/]xmiId[else][prefix/]id[/if] [for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))] [prefix/][p.name/][i/][/for][if (getAllSubClassesForType(aClass) -> size() > 0 )] [prefix/][generateName(aClass).toLowerFirst()/]Type[/if] [/template] [template public generateNameFunction(c:Class,n:NamedElement)] function_[c.name/][if (c <> n.owner)]_[n.owner.oclAsType(NamedElement).name/][/if]_[n.name/] [/template] [template public generateNameFunction(c:Class,s:String)] function_[c.name/]_[s/] [/template] [template public generateNameOperation(c:Class,n:NamedElement)] operatio_[c.name/][if (c <> n.owner)]_[n.owner.oclAsType(NamedElement).name/][/if]_[n.name/] [/template] [template public generateName(n:NamedElement)] [let nOw:NamedElement = n.owner][generateName(nOw).toUpperFirst()/]_[/let][n.name/] [/template] [template public generateType(t : TypedElement) ] [let t:Type = t.type] [if (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Boolean')]Bool[elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'String')] String [elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Integer' or t.name = 'UnlimitedNatural')] Int [elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Real')] Float [else][if (getTypeToBeConsidered(t)->size()=1)][generateName(getTypeToBeConsidered(t)->any(true))/][/if][/if] [/let] [/template] [template public generateDefaultValueForType(t : TypedElement) ] [let t:Type = t.type] [if (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Boolean')]False[elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'String')] ""[elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Integer' or t.name = 'UnlimitedNatural')] 0[elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Real')] 0.0[else][if (getTypeToBeConsidered(t)->size()=1)][generateName(getTypeToBeConsidered(t)->any(true))/][/if][/if] [/let] [/template] [template public generateParameters(o:Operation)] [for (p:Parameter | o.ownedParameter->reject(a|a.direction = ParameterDirectionKind::return))][if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] -> [/for] [/template] [template public generateReturn(o:Operation)] [generateType(getAllParameters(o)->select(a|a.direction = ParameterDirectionKind::return)->any(true))/] [/template] [comment]Compare attributes[/comment] [template public generateOrd(aClass:Class) ] (<=) ([generateDataConstructorParameter(aClass,'a')/]) ([generateDataConstructorParameter(aClass,'b')/]) = (axmiId < bxmiId || axmiId == bxmiId) (<=) ([generateName(aClass)/]Empty) ([generateDataConstructorParameter(aClass,'b')/]) = True (<=) ([generateDataConstructorParameter(aClass,'a')/]) ([generateName(aClass)/]Empty) = False (<=) ([generateName(aClass)/]Empty) ([generateName(aClass)/]Empty) = True [/template] [template public generateEq(aClass:Class) ] (==) ([generateDataConstructorParameter(aClass,'a')/]) ([generateDataConstructorParameter(aClass,'b')/]) = (axmiId == bxmiId) (==) ([generateName(aClass)/]Empty) ([generateDataConstructorParameter(aClass,'b')/]) = False (==) ([generateDataConstructorParameter(aClass,'a')/]) ([generateName(aClass)/]Empty) = False (==) ([generateName(aClass)/]Empty) ([generateName(aClass)/]Empty) = True [/template] [template public generateText(aClass:Class) ] showsPrec i [generateName(aClass)/]Empty = showString("[generateName(aClass)/]Empty") showsPrec i ([generateDataConstructorParameter(aClass,'')/]) = showString(show [if (getAllSubClassesForType(aClass) -> size() > 0 )][generateName(aClass).toLowerFirst()/]Type [else] "[generateName(aClass)/]: " [/if] ++ " name = " ++ [for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))] [if (p.name='name')] [p.name/][i/] [/if][/for] ) [/template] [template public generateCreate(aClass:Class) ] -- -- RULE for creation extracting from the Reserve -- the type used for embedding is not a dynamic function, it is defined during embedding... subset from the set of possible values... rule_[generateName(aClass)/]_create ::[for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))] [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] -> [/for] [if (getAllSubClassesForType(aClass) -> size() > 0 )][generateName(aClass)/]Type ->[/if] Rule [generateName(aClass)/] rule_[generateName(aClass)/]_create [for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))] [p.name/][i/][/for][if (getAllSubClassesForType(aClass) -> size() > 0 )] [generateName(aClass).toLowerFirst()/]Type[/if] = result( [generateName(aClass)/] (head $ newIntegers 1) [for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))] [p.name/][i/][/for][if (getAllSubClassesForType(aClass) -> size() > 0 )] [generateName(aClass).toLowerFirst()/]Type[/if]) [/template] [template public generateOrdEnumeration(aEnum:Enumeration) ] (<=) a b = ((findPos list a) < (findPos list b) || a == b) where list :: ['['/][generateName(aEnum)/][']'/] list = ['['/][for (p:EnumerationLiteral | aEnum.ownedLiteral)][if (i >1)],[/if] [generateName(p)/][/for][']'/] findPos :: ['['/][generateName(aEnum)/][']'/] -> [generateName(aEnum)/] -> Int findPos list elem | head list == elem = 0 | otherwise = 1 + (findPos (tail list) elem) [/template] [template public generateOrdEnumeration(aClass:Class) ] (<=) a b = ((findPos list a) < (findPos list b) || a == b) where list :: ['['/][generateName(aClass)/]Type[']'/] list = ['['/][for (aClass2:Class | getAllSubClassesForType(aClass))][if (i>1 )],[/if][generateName(aClass2)/][/for][']'/] findPos :: ['['/][generateName(aClass)/]Type[']'/] -> [generateName(aClass)/]Type -> Int findPos list elem | head list == elem = 0 | otherwise = 1 + (findPos (tail list) elem) [/template] [comment]SUPPORT CLASSES QUERIES[/comment] [query public getAllSuperClasses(aClass : Class) : Set (Class) = aClass->closure(general.oclAsType(Class))->including(aClass) /] [query public getAllSuperClassesWithoutMe(aClass : Class) : Set (Class) = aClass->closure(general.oclAsType(Class)) /] [query public getAllSubClasses(aClass : Class) : Set (Class) = getTargetClassifiersClosure()->select( a| a->closure(general.oclAsType(Class))->includes(aClass))/] [query public getAllSubClassesForType(aClass : Class) : Set (Class) = getAllSubClasses(aClass)->select(not isAbstract)/] [comment]SUPPORT CLOSURE DEFINITION[/comment] [query public getTargetClassifiers(o:OclAny) : Set (Classifier) = Classifier.allInstances()->select(a|getTargetElements()->includes(a.name)) ->union(PackageImport.allInstances().importedPackage.eAllContents(Classifier)->select(a|getTargetElements()->includes(a.name)))->asSet()/] [query public getKeyClassifiers(o:OclAny) : Set (Classifier) = Classifier.allInstances()->select(getKeyElements()->includes(name)) ->union(PackageImport.allInstances().importedPackage.eAllContents(Classifier)->select(a|getKeyElements()->includes(a.name)))->asSet()/] [query public getTargetClassifiersClosure(o:OclAny) : Set (Classifier) = getTargetClassifiers().oclAsType(Class).getAllSuperClasses() ->union(getTargetClassifiers().oclAsType(Class).getAllSuperClasses().attribute.type) ->union(getTargetClassifiers().oclAsType(Class).getAllSuperClasses().getAllSuperClasses().attribute.type->filter(Class).getAllSuperClasses()) ->asSet() /] [query public isTargetClassifiersClosedUnderKeyClassifiers(o:OclAny) : Boolean = getTargetClassifiersClosure() -> filter(Class) ->select( a| a.getAllSubClasses()->intersection(getKeyClassifiers())->size()=0 and a.getAllSuperClassesWithoutMe()->intersection(getKeyClassifiers())->size()=0) = getKeyClassifiers() /] [query public getClassifiersOutside(o:OclAny) : Set (Classifier) = getKeyClassifiers() -> symmetricDifference(getTargetClassifiersClosure() -> filter(Class) ->select( a| a.getAllSubClasses()->intersection(getKeyClassifiers())->size()=0 and a.getAllSuperClassesWithoutMe()->intersection(getKeyClassifiers())->size()=0) )/] [query public getElementsToBeConsidered(o:OclAny) : Set (Classifier) = getTargetClassifiersClosure()->removeAll(getClassifiersOutside())/] [query public getElementsToBeProcessed(o:OclAny) : Set (Classifier) = getElementsToBeConsidered()->select(a|getKeyClassifiers()->includes(a))->union(getElementsToBeConsidered()->filter(Enumeration))->reject(a|getKeyElementsInOtherModule()->includes(a.name))/] [comment]SUPPORT ATTRIBUTE x CLOSURE EVALUATION[/comment] [query public isAPrimitiveType(t:Type) : Boolean = t.namespace.name = 'PrimitiveTypes' and (t.name = 'Boolean' or t.name = 'String' or t.name = 'Integer' or t.name = 'UnlimitedNatural' or t.name = 'Real')/] [query public getTypeToBeConsidered(t:Type) : Set(Type) = getElementsToBeProcessed()->select(a|a=t)->union(getElementsToBeProcessed()->filter(Class)->select(a|getAllSuperClasses(a)->includes(t) or getAllSubClasses(a)->includes(t) ))->union(getElementsToBeConsidered()->filter(Class)->select(a|getAllSuperClasses(a)->includes(t) or getAllSubClasses(a)->includes(t) )->select(a|getKeyElementsInOtherModule()->includes(a.name)))/] [comment]ATTRIBUTE plus CROSS CUTTING[/comment] [query public getCrossCuttingClassifiers(o:OclAny) : Set (Classifier) = Classifier.allInstances()->select(a|getCrossCuttingElements()->includes(a.name)) ->union(PackageImport.allInstances().importedPackage.eAllContents(Classifier)->select(a|getCrossCuttingElements()->includes(a.name)))->asSet()/] [query public getAllSubClassesPlusCrossCutting(c:Class) : Set (Class) = if getAllSubClasses(c)->closure(general.oclAsType(Class))->intersection(getCrossCuttingClassifiers())->notEmpty() then getAllSubClasses(c)->union(getAllSubClasses(c)->closure(general.oclAsType(Class))->intersection(getCrossCuttingClassifiers()->select(c1|getAllSuperClasses(c)->excludes(c1)))) else getAllSubClasses(c) endif /] [query public getAllAttributes(c:Class) : Set(Property) = getAllSuperClasses(c)->union(getAllSubClassesPlusCrossCutting(c))->filter(Class).ownedAttribute->asSet()/] [query public getAllAttributesToBeGenerated(c:Class) : Set(Property) = getAllAttributes(c)->select(a|not a.isDerived and (isAPrimitiveType(a.type) or getTypeToBeConsidered(a.type)->size()=1) )/] [query public getAllAttributesToBeGeneratedForConstructor(c:Class) : Sequence(Property) = getAllAttributes(c)->select(a|not a.isDerived and (isAPrimitiveType(a.type) or getTypeToBeConsidered(a.type)->size()=1) and a.opposite->isEmpty() and not (shouldBeConsideredInConstructor(a)))->asSequence()->sortedBy(owner.oclAsType(NamedElement).name+name)/] [comment]IN THE SEMANTICS, all attributes are dynamic functions[/comment] [query public shouldBeConsideredInConstructor(a:Property) : Boolean = generateSemantics() /] [comment]SUPPORT OPERATION x CLOSURE EVALUATION[/comment] [query public getAllParameters(o:Operation) : Set(Parameter) = o.ownedParameter/] [query public hasReturn(o:Operation) : Boolean = getAllParameters(o)->exists(a|a.direction = ParameterDirectionKind::return)/] [query public canBeGenerated(o:Operation) : Boolean = getAllParameters(o)->select(a|not a.type.oclIsUndefined() and ((isAPrimitiveType(a.type) or getTypeToBeConsidered(a.type)->size()=1) ))->size() = getAllParameters(o)->size()/] [** * The documentation of the module generate. * ------------------------------------------------------------------------------------------------------------------------------------------------------ *] [template public generateTransformationDataConstructors(aElement : Classifier)] [let aClass : Class = aElement] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- DATA CONSTRUCTORS [aClass.name/] -- [for (aClass2:Class | aClass->asSet()->select(a|not a.isAbstract)->union(getAllSubClassesForType(aClass))->select(a|getTargetClassifiers()->includes(a)))] -- [generateName(aClass2)/] ['['/]for (aClass:[aClass2.name/] | [aClass2.name/].allInstances() [if (getElementsFromOtherModel()->includes(aClass2.name))]->union(PackageImport.allInstances().importedPackage.eAllContents([aClass2.name/]))[/if] [for (aClass3:Class|getAllSubClasses(aClass2)->select(a|getTargetClassifiers()->includes(a)))] - [aClass3.name/].allInstances()[/for])[']'/] ['['/]getComposedName(aClass)/[']'/] ::[generateName(aClass)/] ['['/]getComposedName(aClass)/[']'/] = [generateName(aClass)/] "['['/]getComposedName(aClass)/[']'/]" [for (p:Property | getAllAttributesToBeGeneratedForConstructor(aClass))][generateAttribute(p, aClass2)/] [/for][if (getAllSubClassesForType(aClass) -> size() > 0 )] [generateName(aClass2)/][/if] ['['/]/for[']'/] [/for] [/let] [/template] [template public generateTransformationProperties(aElement : Classifier)] [let aClass : Class = aElement] [for (aClass2:Class | getAllSuperClasses(aClass))] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- FUNCTIONS SUPERCLASSES [aClass2.name/] [aClass.name/] -- [generatePropertyBody(aClass, aClass2)/] [/for] [for (aClass2:Class | getAllSubClasses(aClass))] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- FUNCTIONS SUBCLASSES [aClass2.name/] [aClass.name/] -- [generatePropertyBody(aClass, aClass2)/] [/for] [/let] [/template] [template public generatePropertyBody(aClass:Class, aClass2:Class) ] [for (p:Property | aClass2.ownedAttribute)] [if (p.isDerived)] [if (getTypeToBeConsidered(p.type)->size()=1 and p.type.oclIsKindOf(Class) and p.type.oclAsType(Class).getAllSuperClasses().name->includes('NamedElement') and aClass2.name <> 'Namespace' and aClass2.name <> 'RedefinableElement' and aClass2.name <> 'NamedElement')] -- property NOT generated (DERIVED PROPERTY) [p.name/] [p.type.name/] [comment]generateDerivedPropertyBody(aClass, aClass2, p)/][/comment] [else] -- property NOT generated (DERIVED PROPERTY) [p.name/] [p.type.name/] [/if] [elseif (p.type.isAPrimitiveType() or getTypeToBeConsidered(p.type)->size() = 1)] [if (p.opposite ->isEmpty())] -- property covered by abstract syntax [p.name/] [p.type.name/] [else] -- property NOT covered by abstract syntax (avoided circ. references) [p.name/] [p.type.name/] [generateDerivedPropertyBody(aClass, aClass2, p)/] [/if] [elseif (getTypeToBeConsidered(p.type)->size() > 1)] -- property generated using different data types [p.name/] [p.type.name/] [generatePropertyBodyForMultipleDataTypes(aClass, aClass2, p)/] [else] -- property not generated (TYPE IS NOT IN THE CLOSED SET) [p.name/] [p.type.name/] [/if] [/for] [comment]generating type - type causes circular references so ...[/comment] [if (aClass.getAllSuperClasses()->select(name='TypedElement')->size() = 0 and aClass2->closure(general.oclAsType(Class))->select(name='TypedElement')->size() > 0 and getTypeToBeConsidered(aClass2->closure(general.oclAsType(Class))->select(name='TypedElement').attribute->select(name='type')->any(true).type)->size() = 1)] -- property NOT covered by abstract syntax (avoided circ. references) TypedElement [generateDerivedPropertyBody(aClass, aClass2, aClass2->closure(general.oclAsType(Class))->select(name='TypedElement').attribute->select(name='type')->any(true))/] [/if] [/template] [template public generateDerivedPropertyBody(aClass:Class, aClass2:Class, p:Property) ] [generateNameFunction(aClass2,p)/] :: [if (generateSemantics())] Dynamic ([/if] [generateName(aClass)/] -> [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateType(p)/][elseif (p.isUnique)]{[generateType(p)/]}[elseif (p.isOrdered)] [ '[' /][generateType(p)/][ ']' /][/if] [if (generateSemantics())])[/if] [generateNameFunction(aClass2,p)/] [aClass2.name.toLowerFirst()/]_ = if length elems == 1 then v else [if (p.isUnique and (p.upper > 1 or p.upper = -1))]{}[else][generateType(p)/]Empty[/if] where (_,v) = head elems elems = filter (\(e,v) -> e == [aClass2.name.toLowerFirst()/]_) ['[\'[\'/]'/] ['['/]for (aClass:[aClass2.name/] | [aClass2.name/].allInstances()->select(aClass|aClass.[getNameConsideringBug(p,aClass2)/]->size() > 0 and getCoveredElements()->includes(aClass.eClass().name)))[']'/] ['['/]if (i>1)[']'/],['['/]/if[']'/](['['/]getComposedName(aClass)/[']'/], [if (p.isUnique and (p.upper > 1 or p.upper = -1))]{[/if]['['/]for (aItem:Element | aClass.[getNameConsideringBug(p,aClass2)/])[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/]['['/]if(aItem.oclIsKindOf([getTypeToBeConsidered(p.type)->any(true).name/]) and getCoveredElements()->includes(aItem.eClass().name) [if (getElementsFromOtherModel()->excludes(aClass.name))]and aItem.eContainer(Model) = aClass.eContainer(Model)[/if])[']'/]['['/]getComposedName(aItem)/[']'/]['['/]else[']'/][generateName(getTypeToBeConsidered(p.type)->any(true))/]Empty['['/]/if[']'/]['['/]/for[']'/][if (p.isUnique and (p.upper > 1 or p.upper = -1))]}[/if]) ['['/]/for[']'/] ['[\']\'/]'/] [/template] [template public generatePropertyBodyForMultipleDataTypes(aClass:Class, aClass2:Class, p:Property) ] [for ( type:Type | getTypeToBeConsidered(p.type))] [generateNameFunction(aClass2,p)/]_[type.name/] :: [if (generateSemantics())] Dynamic ([/if] [generateName(aClass)/] -> [if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][generateName(type)/][elseif (p.isUnique)]{[generateName(type)/]}[elseif (p.isOrdered)] [ '[' /][generateName(type)/][ ']' /][/if] [if (generateSemantics())])[/if] [generateNameFunction(aClass2,p)/]_[type.name/] [aClass2.name.toLowerFirst()/]_ = if length elems == 1 then v else [if (p.isUnique and (p.upper > 1 or p.upper = -1))]{}[else][generateType(p)/]Empty[/if] where (_,v) = head elems elems = filter (\(e,v) -> e == [aClass2.name.toLowerFirst()/]_) ['[\'[\'/]'/] ['['/]for (aClass:[aClass2.name/] | [aClass2.name/].allInstances()->select(aClass|aClass.[getNameConsideringBug(p,aClass2)/]->size() > 0 and getCoveredElements()->includes(aClass.eClass().name)))[']'/] ['['/]if (i>1)[']'/],['['/]/if[']'/](['['/]getComposedName(aClass)/[']'/], [if (p.isUnique and (p.upper > 1 or p.upper = -1))]{[/if]['['/]for (aItem:Element | aClass.[getNameConsideringBug(p,aClass2)/])[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/]['['/]if(aItem.oclIsKindOf([type.name/]) and getCoveredElements()->includes(aItem.eClass().name) [if (getElementsFromOtherModel()->excludes(aClass.name))]and aItem.eContainer(Model) = aClass.eContainer(Model)[/if])[']'/]['['/]getComposedName(aItem)/[']'/]['['/]else[']'/][generateName(type)/]Empty['['/]/if[']'/]['['/]/for[']'/][if (p.isUnique and (p.upper > 1 or p.upper = -1))]}[/if]) ['['/]/for[']'/] ['[\']\'/]'/] [/for] [/template] [template public generateAttribute(p:Property,c:Class) ] [let t:Type = p.type][if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][elseif (p.isUnique)]{[elseif (p.isOrdered)][ '[\'[\'/]' /][/if][if (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Boolean')] [if getAllSuperClasses(c).ownedAttribute->includes(p)]['['/]if (aClass.[getNameConsideringBug(p,c)/]->asSequence()->size()=0)[']'/]False['['/]/if[']'/] ['['/]for (aItem:Boolean | aClass.[getNameConsideringBug(p,c)/]->asSequence())[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/] ['['/]aItem.toString().toUpperFirst()/[']'/]['['/]/for[']'/] [else]False[/if][elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'String')] [if getAllSuperClasses(c).ownedAttribute->includes(p)]['['/]if (aClass.[getNameConsideringBug(p,c)/]->asSequence()->size()=0)[']'/]""['['/]/if[']'/] ['['/]for (aItem:String | aClass.[getNameConsideringBug(p,c)/]->asSequence())[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/]"['['/]aItem.replaceAll('\r\n|\n|\r','')/[']'/]"['['/]/for[']'/][else]""[/if] [elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Integer' or t.name = 'UnlimitedNatural')] [if getAllSuperClasses(c).ownedAttribute->includes(p)]['['/]if (aClass.[getNameConsideringBug(p,c)/]->asSequence()->size()=0)[']'/]0['['/]/if[']'/] ['['/]for (aItem:Integer | aClass.[getNameConsideringBug(p,c)/]->asSequence())[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/] (['['/]aItem/[']'/])['['/]/for[']'/] [else]0[/if] [elseif (t.namespace.name = 'PrimitiveTypes') and (t.name = 'Real')] [if getAllSuperClasses(c).ownedAttribute->includes(p)]['['/]if (aClass.[getNameConsideringBug(p,c)/]->asSequence()->size()=0)[']'/]0.0['['/]/if[']'/] ['['/]for (aItem:Real | aClass.[getNameConsideringBug(p,c)/]->asSequence())[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/] (['['/]aItem/[']'/])['['/]/for[']'/] [else]0.0[/if] [elseif (t.oclIsKindOf(Enumeration))] [if getAllSuperClasses(c).ownedAttribute->includes(p)][generateName(t)/]_['['/]aClass.[getNameConsideringBug(p,c)/]/[']'/][else][generateName(t)/]_[t.oclAsType(Enumeration).ownedLiteral.name->any(true)/][/if] [elseif getAllSuperClasses(c).ownedAttribute->includes(p)] ['['/]if (aClass.[getNameConsideringBug(p,c)/]->asSequence()->size()=0)[']'/][generateName(getTypeToBeConsidered(t)->any(true))/]Empty['['/]/if[']'/] ['['/]for (aItem:Element | aClass.[getNameConsideringBug(p,c)/]->asSequence())[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/] ['['/]if(aItem.oclIsKindOf([getTypeToBeConsidered(t)->any(true).name/]) and getCoveredElements()->includes(aItem.eClass().name))[']'/]['['/]getComposedName(aItem)/[']'/]['['/]else[']'/][generateName(getTypeToBeConsidered(t)->any(true))/]Empty['['/]/if[']'/]['['/]/for[']'/] [else] [generateName(getTypeToBeConsidered(t)->any(true))/]Empty[/if][if ((p.lower = 0 or p.lower = 1) and (p.upper = 1))][elseif (p.isUnique)]}[elseif (p.isOrdered)][ '[\']\'/]' /][/if][/let] [/template] [template public generateClosureEvaluation(a:OclAny) ] -- evaluating closure ['['/]for (aElement:Element | aModel.eAllContents()->filter(Element)->reject(oclIsKindOf(Package))->reject(oclIsKindOf(Comment))->reject(oclIsKindOf(PackageImport)) )[']'/] ['['/]if (getCoveredElements()->excludes(aElement.eClass().name))[']'/] -- WARNING: elements from this metaclass ['['/]aElement.eClass().name/[']'/] -- are not embedded ['['/]getComposedName(aElement)/[']'/] ['['/]/if[']'/] ['['/]/for[']'/] [/template] [template public generateTransformationStereotypeFunctions(aElement : Classifier)] [let aClass : Class = aElement] ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- STEREOTYPE Functions [aClass.name/] -- function_[aClass.name/]_AppliedStereotype -- function_[aClass.name/]_InverseAppliedStereotype -- function_[aClass.name/]_EnumerationValueForAppliedStereotype -- [generateName(aClass)/] [generateNameFunction(aClass, 'AppliedStereotype')/] :: [generateName(aClass)/] -> {Stereotype} [generateNameFunction(aClass, 'AppliedStereotype')/] [aClass.name.toLowerFirst()/]_ ['['/]for (aClass:[aClass.name/] | [aClass.name/].allInstances())[']'/] ['['/]if (aClass.getAppliedStereotypes()->size()>0)[']'/] | [aClass.name.toLowerFirst()/]_ == ['['/]getComposedName(aClass)/[']'/] = {['['/]for (aItem:Stereotype | aClass.getAppliedStereotypes())[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/]['['/]if(getCoveredStereotypes()->includes(aItem.name))[']'/]['['/]aItem.name/[']'/]['['/]else[']'/]StereotypeUndef['['/]/if[']'/]['['/]/for[']'/]} ['['/]/if[']'/] ['['/]/for[']'/] | otherwise = {} -- [generateName(aClass)/] [generateNameFunction(aClass, 'InverseAppliedStereotype')/] :: Stereotype -> {[generateName(aClass)/]} [generateNameFunction(aClass, 'InverseAppliedStereotype')/] stereotype_ ['['/]for (aItem:String | [aClass.name/].allInstances().getAppliedStereotypes().name->asSet()->intersection(getCoveredStereotypes()))[']'/] | stereotype_ == ['['/]aItem/[']'/] = {['['/]for (aClass: [aClass.name/] | [aClass.name/].allInstances()->select((getAppliedStereotypes()->select(s|s.name=aItem))->size() > 0))[']'/]['['/]if(i>1)[']'/],['['/]/if[']'/]['['/]getComposedName(aClass)/[']'/]['['/]/for[']'/]} ['['/]/for[']'/] | otherwise = {} [generateNameFunction(aClass, 'EnumerationValueForAppliedStereotype')/] :: [generateName(aClass)/] -> Stereotype -> StereotypeTag -> StereotypeTagValue [generateNameFunction(aClass, 'EnumerationValueForAppliedStereotype')/] [aClass.name.toLowerFirst()/]_ s st ['['/]for (aClass:[aClass.name/] | [aClass.name/].allInstances())[']'/] ['['/]if (aClass.getAppliedStereotypes()->size()>0)[']'/] ['['/]for (st:Stereotype | aClass.getAppliedStereotypes())[']'/] ['['/]if (st.attribute->select(type.eClass().name='Enumeration')->size()>0)[']'/] ['['/]for (s:String | st.attribute->select(type.eClass().name='Enumeration').name)[']'/] ['['/]if (not aClass.getValue(st, s).oclAsType(EnumerationLiteral).name.oclIsInvalid())[']'/] | [aClass.name.toLowerFirst()/]_ == ['['/]getComposedName(aClass)/[']'/] && s == ['['/]st.name/[']'/] && st == ['['/]s.toUpperFirst()/[']'/] = ['['/]aClass.getValue(st, s).oclAsType(EnumerationLiteral).name.toUpperFirst()/[']'/] ['['/]/if[']'/] ['['/]/for[']'/] ['['/]/if[']'/] ['['/]/for[']'/] ['['/]/if[']'/] ['['/]/for[']'/] | otherwise = StereotypeTagValueUndef [for (aItem:String | getElementsToBeGeneratedStereotype())] [generateNameFunction(aClass, aItem.concat('ForAppliedStereotype'))/] :: [generateName(aClass)/] -> Stereotype -> StereotypeTag -> [generateName(getKeyClassifiers()->select(a|a.name=aItem)->any(true))/] [generateNameFunction(aClass, aItem.concat('ForAppliedStereotype'))/] [aClass.name.toLowerFirst()/]_ s st ['['/]for (aClass:[aClass.name/] | [aClass.name/].allInstances())[']'/] ['['/]if (aClass.getAppliedStereotypes()->size()>0)[']'/] ['['/]for (st:Stereotype | aClass.getAppliedStereotypes())[']'/] ['['/]for (s:String | getCoveredStereotypeAttributes()->reject(e| aClass.getValue(st, e).oclIsInvalid() or aClass.getValue(st, e).oclAsType([aItem/]).oclIsInvalid() ))[']'/] | [aClass.name.toLowerFirst()/]_ == ['['/]getComposedName(aClass)/[']'/] && s == ['['/]st.name/[']'/] && st == ['['/]s.toUpperFirst()/[']'/] = ['['/]getComposedName(aClass.getValue(st, s).oclAsType(Element))/[']'/] ['['/]/for[']'/] ['['/]/for[']'/] ['['/]/if[']'/] ['['/]/for[']'/] | otherwise = [generateName(getKeyClassifiers()->select(a|a.name=aItem)->any(true))/]Empty [/for] [/let] [/template] [comment]SUPPORT NAME WITH ERROR "ERROR" FOUND IN THE ECLIPSE http://wiki.eclipse.org/MDT/UML2/UML2_4.0_Migration_Guide Changes in the revised UML 2.4.1 specification (to resolve issue 16232) also required the following changes: Non-compliant Activity::ownedNode and Activity::ownedGroup properties were introduced to compose nodes and groups which are not structured activity nodes. [/comment] [query public getNameConsideringBug(p:Property, c:Class) : String = p.name->asSet()->union('ownedNode'->asSet()->reject(c.name <> 'Activity'))->reject(a|a='node' and c.name = 'Activity')->any(true) ->asSequence()->append('_context')->reject(a|a='context')->first() ->asSequence()->append('_body')->reject(a|a='body')->first()/] [comment]Help queries for the generated transformation[/comment] [template public generateHelpQueries(a:OclAny) ] ['['/]query public getID(aElement : Element) : String = invoke('org.hybridfuml.transformations.helper.XMIIDHelper','getXMIID(org.eclipse.emf.ecore.EObject)', Sequence{aElement})/[']'/] ['['/]query public filterSpecialCharacteres(str : String) : String = if str.startsWith('_') or str.startsWith('0') or str.startsWith('1') or str.startsWith('2') or str.startsWith('3') or str.startsWith('4') or str.startsWith('5') or str.startsWith('6') or str.startsWith('7') or str.startsWith('8') or str.startsWith('9') then 'g'+str.replaceAll('['['/]+[']'/]', 'add_').replaceAll('['['/]*[']'/]', 'mult_').replaceAll('['['/]/[']'/]', 'div_').replaceAll('['['/]=[']'/]', 'equals_').replaceAll('['['/]-[']'/]', 'minus_').replaceAll('['['/]<[']'/]', 'lt_').replaceAll('['['/]>[']'/]', 'gt_').replaceAll('['['/].[']'/]', 'dot_') else str.replaceAll('['['/]+[']'/]', 'add_').replaceAll('['['/]*[']'/]', 'mult_').replaceAll('['['/]/[']'/]', 'div_').replaceAll('['['/]=[']'/]', 'equals_').replaceAll('['['/]-[']'/]', 'minus_').replaceAll('['['/]<[']'/]', 'lt_').replaceAll('['['/]>[']'/]', 'gt_').replaceAll('['['/].[']'/]', 'dot_') endif /[']'/] ['['/]query public getComposedName(aElement : Element) : String = if aElement.owner.oclIsKindOf(Model) and aElement.oclIsKindOf(Activity) and aElement.oclAsType(NamedElement).name = 'Main' then 'main' else filterSpecialCharacteres(getID(aElement)).toLowerFirst() endif/[']'/] ['['/]query public getCoveredElements( a: OclAny) : Set(String) = Set{[for (aClass:String | getTargetElements())] [if(i>1)],[/if]'[aClass/]'[/for]}/[']'/] ['['/]query public getCoveredStereotypes( a: OclAny) : Set(String) = Set{[for (aClass:String | getAllowedStereotypes())] [if(i>1)],[/if]'[aClass/]'[/for]}/[']'/] ['['/]query public getCoveredStereotypeAttributes( a: OclAny) : Set(String) = Set{[for (aClass:String | getElementsToBeGeneratedStereotypeAttribute())] [if(i>1)],[/if]'[aClass/]'[/for]}/[']'/] [/template]